package com.quectel.cms.controller.scheduling;


import cn.hutool.core.lang.func.LambdaUtil;
import com.quectel.business.common.scheduling.SchedulingPersonBusiness;
import com.quectel.cms.controller.BaseController;
import com.quectel.cms.util.SessionHolder;
import com.quectel.cms.vo.scheduling.PersonGroupSetFixShiftVo;
import com.quectel.cms.vo.scheduling.SchedulingAttendanceGroupSetFixShiftReq;
import com.quectel.constant.core.scheduling.SchedulingAttendanceGroupConstants;
import com.quectel.constant.global.SystemConstants;
import com.quectel.constant.global.annotation.RequirePermissions;
import com.quectel.core.module.dept.dto.DeptPersonDto;
import com.quectel.core.module.dept.service.DeptPersonService;
import com.quectel.core.module.notice.dto.NoticeDto;
import com.quectel.core.module.scheduling.dto.*;
import com.quectel.core.module.scheduling.service.*;
import com.quectel.util.common.JacksonUtils;
import com.quectel.util.common.Page;
import com.quectel.util.common.Request;
import com.quectel.util.common.Response;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author zhangheng
 * @email nolan.zhang@quectel.com
 * @date 2023/07/05 13:24
 */
@RestController
@RequestMapping("schedulingAttendanceGroup")
@Tag(name = "SchedulingAttendanceGroupController", description = "考勤组管理相关api")
public class SchedulingAttendanceGroupController extends BaseController {

    @DubboReference
    private SchedulingAttendanceGroupService schedulingAttendanceGroupService;
    @DubboReference
    private SchedulingAttendanceGroupPersonBindingService personBindingService;
    @DubboReference
    private SchedulingAttendanceGroupHeadBindingService headBindingService;
    @DubboReference
    private SchedulingAttendanceGroupPersonWorkTimeConfigService personWorkTimeConfigService;

    @DubboReference
    private DeptPersonService deptPersonService;
    @DubboReference
    private SchedulingTimeConfigService schedulingTimeConfigService;

    @Autowired
    private SchedulingPersonBusiness schedulingPersonBusiness;

    @PostMapping("updateStatus")
    @RequirePermissions(values = "schedulingAttendanceGroup:edit")
    @Operation(summary = "启用禁用考勤组状态")
    public Response<Object> updateStatus(@RequestBody SchedulingAttendanceGroupDto groupDto) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);

        SchedulingAttendanceGroupDto schedulingAttendanceGroupDto = schedulingAttendanceGroupService.selectById(groupDto.getId());
        if (schedulingAttendanceGroupDto == null){
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        if (schedulingAttendanceGroupDto.getLatitude() == null || schedulingAttendanceGroupDto.getLongitude() == null){
            return Response.error("您未对考勤地点设置,请先设置考勤地点信息");
        }

        //填充基础数据
        fillEditCommonData(groupDto);


        schedulingAttendanceGroupService.updateById(groupDto);

        return Response.ok();
    }



    @GetMapping("queryListByVillageAndType")
    @Operation(summary = "根据小区id和类型，查询考勤组")
    public Response<List<SchedulingAttendanceGroupDto>> queryListByVillageAndType(
            @RequestParam(required = false) Long villageId
    ) {

        Map<String, Object> params = Request.parseParams(httpServletRequest);
        super.fillAuthorityData(params);

        // 查询手动排班
        params.put(LambdaUtil.getFieldName(SchedulingAttendanceGroupDto::getVillageId), villageId);
        params.put(LambdaUtil.getFieldName(SchedulingAttendanceGroupDto::getShiftSystemType),
                SchedulingAttendanceGroupConstants.SchedulingTypeEnum.SCHEDULING.getType());

        List<SchedulingAttendanceGroupDto> list = schedulingAttendanceGroupService.queryList(params);

        return Response.<List<SchedulingAttendanceGroupDto>>ok().wrap(list);
    }

    @GetMapping("selectFixedShiftSettingsByGroupId")
    @RequirePermissions(values = "schedulingAttendanceGroup:edit")
    @Operation(summary = "查询当前考勤组绑定的固定排班设置")
    public Response<Object> selectFixedShiftSettingsByGroupId(@RequestParam Long groupId){

        // 判断是否为空
        SchedulingAttendanceGroupDto schedulingAttendanceGroupDto = schedulingAttendanceGroupService.selectById(groupId);
        if (schedulingAttendanceGroupDto == null || !schedulingAttendanceGroupDto.getShiftSystemType().equals(SystemConstants.YES)){
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        SchedulingAttendanceGroupPersonWorkTimeConfigDto personWorkTimeConfigDbValue = personWorkTimeConfigService.selectOne(groupId);
        String timeConfigArr = personWorkTimeConfigDbValue.getTimeConfigArr();

        List<PersonGroupSetFixShiftVo> execInfos = JacksonUtils.parseArray(timeConfigArr, PersonGroupSetFixShiftVo.class);
        return Response.ok().wrap(execInfos);
    }

    /**
     * 固定班绑定时间段动作
     */
    @PostMapping("setFixedShift")
    @RequirePermissions(values = "schedulingAttendanceGroup:edit")
    @Operation(summary = "固定班绑定时间段动作")
    public Response<Object> setFixedShift(@RequestBody @Validated SchedulingAttendanceGroupSetFixShiftReq setFixShiftVo) {

        // 判断是否为空
        SchedulingAttendanceGroupDto schedulingAttendanceGroupDto =
                schedulingAttendanceGroupService.selectById(setFixShiftVo.getSchedulingAttendanceGroupId());
        if (schedulingAttendanceGroupDto == null || !schedulingAttendanceGroupDto.getShiftSystemType().equals(SystemConstants.YES)){
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        try {
            SchedulingAttendanceGroupPersonWorkTimeConfigDto personWorkTimeConfigDbValue =
                    personWorkTimeConfigService.selectOne(setFixShiftVo.getSchedulingAttendanceGroupId());

            // 处理页面传过来的时间段,保存到数据库
            List<SchedulingAttendanceGroupSetFixShiftReq.ExecInfo> submitTimeList = setFixShiftVo.getSubmitTimeList();
            List<PersonGroupSetFixShiftVo> saveDb = new ArrayList<>();
            for (SchedulingAttendanceGroupSetFixShiftReq.ExecInfo execInfo : submitTimeList) {

                PersonGroupSetFixShiftVo setFixShift = new PersonGroupSetFixShiftVo();
                List<SchedulingTimeConfigDto> timeConfigDtoList = new ArrayList<>();
                int day = execInfo.getDay();
                setFixShift.setDay(day);
                List<Long> timeConfigIds = execInfo.getTimeConfigIds();
                if (CollectionUtils.isNotEmpty(timeConfigIds)){
                    for (Long timeConfigId : timeConfigIds) {
                        SchedulingTimeConfigDto schedulingTimeConfigDto = schedulingTimeConfigService.selectById(timeConfigId);
                        if (schedulingTimeConfigDto!= null){
                            timeConfigDtoList.add(schedulingTimeConfigDto);
                        }
                        setFixShift.setTimeConfigDtoList(timeConfigDtoList);
                    }
                }else {
                    setFixShift.setTimeConfigDtoList(new ArrayList<>());
                }
                saveDb.add(setFixShift);
            }

            String timeArrJson = JacksonUtils.toJsonString(saveDb);

            // 数据库中是否存在绑定关系
            if (personWorkTimeConfigDbValue != null){
                SchedulingAttendanceGroupPersonWorkTimeConfigDto updately = new SchedulingAttendanceGroupPersonWorkTimeConfigDto();
                updately.setId(personWorkTimeConfigDbValue.getId());
                updately.setTimeConfigArr(timeArrJson);
                personWorkTimeConfigService.updateById(updately);
            }else {
                SchedulingAttendanceGroupPersonWorkTimeConfigDto savely = new SchedulingAttendanceGroupPersonWorkTimeConfigDto();
                savely.setSchedulingAttendanceGroupId(setFixShiftVo.getSchedulingAttendanceGroupId());
                savely.setTimeConfigArr(timeArrJson);
                personWorkTimeConfigService.save(savely);
            }


        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return Response.ok();
    }

    /**
     * 修改
     *
     * @param schedulingAttendanceGroupDto
     * @return
     */
    @PostMapping("updateAddressInfo")
    @RequirePermissions(values = "schedulingAttendanceGroup:edit")
    @Operation(summary = "根据id修改考勤组打卡位置信息")
    public Response<Object> updateAddressInfo(@RequestBody  @Validated SchedulingAttendanceGroupDto schedulingAttendanceGroupDto) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);
        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(schedulingAttendanceGroupDto.getId()));
        if (schedulingAttendanceGroupService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }
        //填充基础数据
        fillEditCommonData(schedulingAttendanceGroupDto);

        schedulingAttendanceGroupService.updateById(schedulingAttendanceGroupDto);

        return Response.ok();
    }

    /**
     * 分页查询
     *
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("list")
    @RequirePermissions(values = "schedulingAttendanceGroup:list")
    @Operation(summary = "分页获取考勤组管理列表")
    public Response<Page<SchedulingAttendanceGroupDto>> list(
            @Parameter(description = "从1开始的页码数") @RequestParam Integer pageNo,
            @Parameter(description = "每页多少条") @RequestParam Integer pageSize
    ) {
        //查询列表数据
        Request request = Request.configParams(Request.parseParams(httpServletRequest));

        if (StringUtils.isNotEmpty(request.getString("headPersonName"))){
            List<Long> groupIds = schedulingPersonBusiness.headPersonIds(SessionHolder.getSysUser().getTenantId(),
                    request.getString("headPersonName")
                    );
            if (CollectionUtils.isNotEmpty(groupIds)){
                request.put(SystemConstants.ENTITY_ID_COLLECTION_FLAG, groupIds);
            }else {
                request.put(SystemConstants.ENTITY_ID_FLAG, SystemConstants.NONEXISTENT_ID);
            }
        }

        super.fillAuthorityData(request.getParams());
        int total = schedulingAttendanceGroupService.queryTotal(request.getParams());

        List<SchedulingAttendanceGroupDto> list = null;
        if (total > 0) {
            list = schedulingAttendanceGroupService.queryList(request.getParams());
        } else {
            list = new ArrayList<>();
        }

        Page<SchedulingAttendanceGroupDto> page = new Page<>(request.getPageNo(), request.getPageSize(), total, list);
        return Response.<Page<SchedulingAttendanceGroupDto>>ok().wrap(page);
    }

    /**
     * 编辑查询反显
     *
     * @param id
     * @return
     */
    @GetMapping("infoForEdit/{id}")
    @RequirePermissions(values = "schedulingAttendanceGroup:edit")
    @Operation(summary = "在编辑时根据id查询考勤组管理详情")
    public Response<SchedulingAttendanceGroupDto> infoForEdit(@PathVariable("id") Long id) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);
        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));
        if (schedulingAttendanceGroupService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        SchedulingAttendanceGroupDto schedulingAttendanceGroupDto = schedulingAttendanceGroupService.selectById(id);

        List<DeptPersonDto> headPersonDtoList = new ArrayList<>();
        // 填充绑定考勤组负责人列表
        List<SchedulingAttendanceGroupHeadBindingDto> dbHeadBindList = headBindingService.selectListByGroupId(id);
        if (CollectionUtils.isNotEmpty(dbHeadBindList)) {
            for (SchedulingAttendanceGroupHeadBindingDto bindingDto : dbHeadBindList) {
                DeptPersonDto personDto = deptPersonService.selectCacheById(bindingDto.getPersonId());
                if (personDto != null) {
                    headPersonDtoList.add(personDto);
                }
            }
        }
        schedulingAttendanceGroupDto.setHeadPersonList(headPersonDtoList);

        List<DeptPersonDto> personDtoList = new ArrayList<>();
        // 填充绑定的考勤组人员
        List<SchedulingAttendanceGroupPersonBindingDto> dbPersonBindList = personBindingService.selectListByGroupId(id);
        if (CollectionUtils.isNotEmpty(dbPersonBindList)) {
            for (SchedulingAttendanceGroupPersonBindingDto bindingDto : dbPersonBindList) {
                DeptPersonDto personDto = deptPersonService.selectCacheById(bindingDto.getPersonId());
                if (personDto != null) {
                    personDtoList.add(personDto);
                }
            }
        }
        schedulingAttendanceGroupDto.setPersonList(personDtoList);

        return Response.<SchedulingAttendanceGroupDto>ok().wrap(schedulingAttendanceGroupDto);
    }

    /**
     * 详情
     *
     * @param id
     * @return
     */
    @GetMapping("info/{id}")
    @RequirePermissions(values = "schedulingAttendanceGroup:info")
    @Operation(summary = "根据id查询考勤组管理的详情")
    public Response<SchedulingAttendanceGroupDto> info(@PathVariable("id") Long id) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);
        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));
        if (schedulingAttendanceGroupService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        SchedulingAttendanceGroupDto schedulingAttendanceGroupDto = schedulingAttendanceGroupService.selectById(id);

        return Response.<SchedulingAttendanceGroupDto>ok().wrap(schedulingAttendanceGroupDto);
    }

    /**
     * 保存
     *
     * @param schedulingAttendanceGroupDto
     * @return
     */
    @PostMapping("save")
    @RequirePermissions(values = "schedulingAttendanceGroup:edit")
    @Operation(summary = "新增考勤组管理")
    public Response<Object> save(@RequestBody @Validated SchedulingAttendanceGroupDto schedulingAttendanceGroupDto) {

        //填充基础数据
        fillSaveCommonData(schedulingAttendanceGroupDto);

        if (CollectionUtils.isEmpty(schedulingAttendanceGroupDto.getHeadPersonList())
                ||  CollectionUtils.isEmpty(schedulingAttendanceGroupDto.getPersonList())
        ){
            return Response.error("考勤组负责人或考勤组人员不能为空");
        }

        schedulingAttendanceGroupService.saveOrUpdate(schedulingAttendanceGroupDto);

        return Response.ok();
    }


    /**
     * 修改
     *
     * @param schedulingAttendanceGroupDto
     * @return
     */
    @PostMapping("update")
    @RequirePermissions(values = "schedulingAttendanceGroup:edit")
    @Operation(summary = "根据id修改考勤组管理")
    public Response<Object> update(@RequestBody  @Validated SchedulingAttendanceGroupDto schedulingAttendanceGroupDto) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);
        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(schedulingAttendanceGroupDto.getId()));
        if (schedulingAttendanceGroupService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        // 限制禁止修改排班类型
        SchedulingAttendanceGroupDto dbValue = schedulingAttendanceGroupService.selectById(schedulingAttendanceGroupDto.getId());
        if (dbValue == null ){
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }
        if (!dbValue.getShiftSystemType().equals(schedulingAttendanceGroupDto.getShiftSystemType())){
            return Response.error("不允许修改排班类型");
        }

        //填充基础数据
        fillEditCommonData(schedulingAttendanceGroupDto);

        schedulingAttendanceGroupService.saveOrUpdate(schedulingAttendanceGroupDto);

        return Response.ok();
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @PostMapping("delete")
    @RequirePermissions(values = "schedulingAttendanceGroup:delete")
    @Operation(summary = "根据多条记录id批量删除考勤组管理")
    public Response<Object> delete(@RequestBody Long[] ids) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);

        for (Long id : ids) {

            params.remove(SystemConstants.ENTITY_ID_FLAG);
            params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));

            if (schedulingAttendanceGroupService.queryTotal(params) <= 0) {
                return Response.error(SystemConstants.ILLEGAL_MSG);
            }
        }

        // 查询是否有绑定人员的数据，绑定了不允许删除，先删除绑定的人
        for (Long id : ids) {
            List<SchedulingAttendanceGroupPersonBindingDto> schedulingAttendanceGroupPersonBindingDtos =
                    personBindingService.selectListByGroupId(id);
            if (CollectionUtils.isNotEmpty(schedulingAttendanceGroupPersonBindingDtos)){
                return Response.error("请先解除考勤组负责人关系");
            }
            List<SchedulingAttendanceGroupHeadBindingDto> schedulingAttendanceGroupHeadBindingDtos =
                    headBindingService.selectListByGroupId(id);
            if (CollectionUtils.isNotEmpty(schedulingAttendanceGroupHeadBindingDtos)){
                return Response.error("请先解除考勤组参与人关系");
            }
        }

        schedulingAttendanceGroupService.deleteBatch(ids);

        return Response.ok();
    }
}
